package com.yc.testupload.controller;

import com.yc.testupload.dao.UserDAO;
import com.yc.testupload.model.User;
import com.yc.testupload.util.EnvironmentManager;
import com.yc.testupload.util.RedisUtil;
import org.json.JSONObject;

import jakarta.servlet.ServletException;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.servlet.http.HttpSession;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import java.io.IOException;
import java.io.PrintWriter;

@WebServlet(name = "loginServlet", value = "/login")
public class LoginServlet extends HttpServlet {

    private static final Logger logger = LogManager.getLogger(LoginServlet.class);
    // 线上部署的顶级域名（手动指定，确保Cookie Domain正确）
    private static final String ONLINE_DOMAIN = "didaproject.com";

    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        request.setCharacterEncoding("UTF-8");
        response.setContentType("application/json;charset=utf-8");
        PrintWriter out = response.getWriter();

        // 获取请求参数
        String username = request.getParameter("username");
        String password = request.getParameter("password");
        String rememberMe = request.getParameter("rememberMe");
        String environment = request.getParameter("environment");

        // 处理环境参数，在登录前切换到选择的环境
        if (environment != null && !environment.isEmpty()) {
            logger.info("用户选择的环境: {}", environment);
            EnvironmentManager envManager = EnvironmentManager.getInstance();
            envManager.switchEnvironment(environment);
        }

        logger.info("接收到登录请求，用户名: {}", username);

        try {
            // 参数验证
            if (username == null || username.isEmpty() || password == null || password.isEmpty()) {
                logger.warn("登录失败：参数不完整");
                out.write("{\"code\":1,\"message\":\"用户名或密码不能为空\"}");
                return;
            }

            // 使用UserDAO验证用户
            UserDAO userDAO = new UserDAO();
            User user = userDAO.getUserByUsernameAndPassword(username, password);

            if (user != null) {
                // 登录成功，创建会话
                HttpSession session = request.getSession();
                session.setAttribute("username", user.getUserName());
                session.setAttribute("userId", user.getUserId());

                // 设置会话过期时间（秒）
                int maxInactiveInterval;
                if ("on".equals(rememberMe)) {
                    maxInactiveInterval = 7 * 24 * 60 * 60; // 7天
                    logger.info("开始设置持久登录Cookie，用户: {}，过期时间: {}秒", username, maxInactiveInterval);

                    // 强制设置Cookie的Domain、Path、HttpOnly等属性
                    String domain = getDomainFromRequest(request);

                    // 先清除可能存在的旧Cookie，避免冲突
                    clearLoginCookiesInternal(response, domain);

                    // 用户名Cookie - 强制配置
                    String usernameCookieStr = String.format(
                            "username=%s; Max-Age=%d; Path=/; HttpOnly=true; SameSite=Lax; Secure=false; Domain=%s",
                            user.getUserName(), maxInactiveInterval, domain);
                    response.addHeader("Set-Cookie", usernameCookieStr);
                    logger.info(
                            "创建username Cookie: {}={}, 路径=/, HttpOnly=true, SameSite=Lax, 过期时间={}秒, 域名={}",
                            "username", user.getUserName(), maxInactiveInterval, domain);

                    // 用户ID Cookie - 强制配置
                    String userIdCookieStr = String.format(
                            "userId=%d; Max-Age=%d; Path=/; HttpOnly=true; SameSite=Lax; Secure=false; Domain=%s",
                            user.getUserId(), maxInactiveInterval, domain);
                    response.addHeader("Set-Cookie", userIdCookieStr);
                    logger.info(
                            "创建userId Cookie: {}={}, 路径=/, HttpOnly=true, SameSite=Lax, 过期时间={}秒, 域名={}",
                            "userId", user.getUserId(), maxInactiveInterval, domain);

                    // 持久化标识Cookie - 强制配置
                    String persistentCookieStr = String.format(
                            "persistent_login=true; Max-Age=%d; Path=/; HttpOnly=true; SameSite=Lax; Secure=false; Domain=%s",
                            maxInactiveInterval, domain);
                    response.addHeader("Set-Cookie", persistentCookieStr);
                    logger.info(
                            "创建persistent_login Cookie: persistent_login=true, 路径=/, HttpOnly=true, SameSite=Lax, 过期时间={}秒, 域名={}",
                            maxInactiveInterval, domain);
                    logger.info("已成功设置所有登录Cookie，用户: {}", username);
                } else {
                    maxInactiveInterval = 30 * 60; // 30分钟
                }
                session.setMaxInactiveInterval(maxInactiveInterval);

                // 保存会话数据到Redis（强制持久化）
                String sessionId = session.getId();
                JSONObject sessionJson = new JSONObject();
                sessionJson.put("username", user.getUserName());
                sessionJson.put("userId", user.getUserId());
                sessionJson.put("persistent_login", "on".equals(rememberMe) ? "true" : "false");
                boolean redisSaveSuccess = RedisUtil.set("session:" + sessionId, sessionJson.toString(),
                        maxInactiveInterval);
                if (redisSaveSuccess) {
                    logger.info("会话数据已保存到Redis，ID: {}, 过期时间: {}秒", sessionId, maxInactiveInterval);
                } else {
                    logger.error("会话数据保存到Redis失败，ID: {}", sessionId);
                }

                logger.info("用户 {} 登录成功", username);
                out.write(
                        String.format("{\"code\":0,\"message\":\"登录成功\",\"data\":{\"username\":\"%s\",\"userId\":%d}}",
                                user.getUserName(), user.getUserId()));
            } else {
                // 登录失败
                logger.warn("用户 {} 登录失败，用户名或密码错误", username);
                out.write("{\"code\":1,\"message\":\"用户名或密码错误\"}");
            }
        } catch (Exception e) {
            logger.error("登录过程中发生错误: {}", e.getMessage(), e);
            out.write("{\"code\":500,\"message\":\"系统错误，请稍后重试\"}");
        } finally {
            out.flush();
            out.close();
        }
    }

    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        // 重定向到登录页面
        response.sendRedirect("/login.html");
    }

    // 从请求中提取域名（本地自动识别，线上强制指定）
    private String getDomainFromRequest(HttpServletRequest request) {
        String serverName = request.getServerName();
        // 本地环境（localhost/IP）不设置Domain
        if (serverName.equals("localhost") || serverName.matches("\\d+\\.\\d+\\.\\d+\\.\\d+")) {
            logger.info("当前为本地环境，不设置Cookie Domain");
            return null;
        }
        // 线上环境强制使用配置的顶级域名
        logger.info("当前为线上环境，强制设置Cookie Domain: {}", ONLINE_DOMAIN);
        return ONLINE_DOMAIN;
    }

    // 内部方法：清除特定Cookie，避免多次设置冲突
    private void clearLoginCookiesInternal(HttpServletResponse response, String domain) {
        String cookiesToClear[] = { "username", "userId", "persistent_login" };
        for (String cookieName : cookiesToClear) {
            String cookieStr = String.format("%s=; Max-Age=0; Path=/; HttpOnly; SameSite=Lax; Secure=false%s",
                    cookieName, domain != null ? "; Domain=" + domain : "");
            response.addHeader("Set-Cookie", cookieStr);
            logger.debug("已清除旧的{} Cookie", cookieName);
        }
    }
}